﻿using System;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
using Ex05.MemoryGameLogic;

namespace Ex05.MemoryGameGraphicalUI
{
    public class MemoryGameForm : Form
    {
        private const int k_ButtonHeightWidth = 45;

        private Game m_Game;
        private Label m_CurrentPlayerLabel;
        private Label m_FirstPlayerLabel;
        private Label m_SecondPlayerLabel;
        private Color m_FirstPlayerColor = Color.GreenYellow;
        private Color m_SecondPlayerColor = Color.CornflowerBlue;
        private Dictionary<Cell, ButtonWithLocation> m_CellToButtonWithLocation;
        private Button m_FirstCellTemporarilyOpenButton;
        private Button m_SecondCellTemporarilyOpenButton;

        public MemoryGameForm(Game i_Game)
        {
            m_Game = i_Game;
            m_CellToButtonWithLocation = new Dictionary<Cell, ButtonWithLocation>();

            initializeComponents();

            m_Game.CellOpened += new CellOpenedEventHandler(m_Game_CellOpened);
            m_Game.TurnSwitched += new TurnSwitchedEventHandler(m_Game_TurnSwitched);
            m_Game.ScoreChanged += new ScoreChangedEventHandler(m_Game_ScoreChanged);
            m_Game.GameEnded += new GameEndedEventHandler(m_Game_GameEnded);

            m_Game.StartRound();
        }

        private void initializeComponents()
        {
            initializeButtons();

            int bottom = getBottomOfMostBottomControl();

            m_CurrentPlayerLabel = new Label();
            m_FirstPlayerLabel = new Label();
            m_SecondPlayerLabel = new Label();

            m_CurrentPlayerLabel.AutoSize = true;
            m_FirstPlayerLabel.AutoSize = true;
            m_SecondPlayerLabel.AutoSize = true;

            m_CurrentPlayerLabel.Location = new Point(12, bottom + 12);
            m_FirstPlayerLabel.Location = new Point(m_CurrentPlayerLabel.Left, m_CurrentPlayerLabel.Bottom);
            m_SecondPlayerLabel.Location = new Point(m_FirstPlayerLabel.Left, m_FirstPlayerLabel.Bottom);

            m_FirstPlayerLabel.BackColor = m_FirstPlayerColor;
            m_SecondPlayerLabel.BackColor = m_SecondPlayerColor;

            this.Controls.Add(m_CurrentPlayerLabel);
            this.Controls.Add(m_FirstPlayerLabel);
            this.Controls.Add(m_SecondPlayerLabel);

            setCurrentPlayerLabelText();
            setFirstPlayerLabel();
            setSecondPlayerLabel();

            this.Text = "Memory Game";
            this.MaximizeBox = false;
            
            adjustFormSize();
            
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
        }

        private void setFirstPlayerLabel()
        {
            string labelText = string.Format("{0}: {1} Pair(s)", m_Game.FirstPlayerName, m_Game.FirstPlayerWithScore.Score);
            m_FirstPlayerLabel.Text = labelText;
        }

        private void setSecondPlayerLabel()
        {
            string labelText = string.Format("{0}: {1} Pair(s)", m_Game.SecondPlayerName, m_Game.SecondPlayerWithScore.Score);
            m_SecondPlayerLabel.Text = labelText;
        }

        private void setCurrentPlayerLabelText()
        {
            string labelText = string.Format("Current Player: {0}", m_Game.CurrentlyPlayingPlayer.Name);
            m_CurrentPlayerLabel.Text = labelText;

            if (m_Game.CurrentlyPlayingPlayer.Equals(m_Game.FirstPlayerWithScore.Player))
            {
                m_CurrentPlayerLabel.BackColor = m_FirstPlayerColor;
            }
            else
            {
                m_CurrentPlayerLabel.BackColor = m_SecondPlayerColor;
            }
        }

        private void initializeButtons()
        {
            for(int row = 0; row < m_Game.BoardSize.Height; row++)
            {
                for (int column = 0; column < m_Game.BoardSize.Width; column++)
                {
                    initButtonWithLocation(row, column);
                }
            }
        }

        private void adjustFormSize()
        {
            int right = getRightOfMostRightControl();
            int bottom = getBottomOfMostBottomControl();
            this.Size = new Size(
                right + this.Size.Width - this.ClientSize.Width + 2,
                bottom + this.Size.Height - this.ClientSize.Height + 2);
        }

        private int getRightOfMostRightControl()
        {
            int right = 0;

            foreach(Control control in this.Controls)
            {
                if(control.Right > right)
                {
                    right = control.Right;
                }
            }

            return right;
        }

        private int getBottomOfMostBottomControl()
        {
            int bottom = 0;

            foreach (Control control in this.Controls)
            {
                if (control.Bottom > bottom)
                {
                    bottom = control.Bottom;
                }
            }

            return bottom;
        }

        private void initButtonWithLocation(int i_Row, int i_Column)
        {
            ButtonWithLocation buttonWithLocation = new ButtonWithLocation(i_Row, i_Column);
            buttonWithLocation.Size = new Size(k_ButtonHeightWidth, k_ButtonHeightWidth);
            int buttonX = 12 + (buttonWithLocation.Column * k_ButtonHeightWidth) + (buttonWithLocation.Column * 8);
            int buttonY = 12 + (buttonWithLocation.Row * k_ButtonHeightWidth) + (buttonWithLocation.Row * 8);
            buttonWithLocation.Location = new Point(buttonX, buttonY);
            buttonWithLocation.Click += new EventHandler(buttonWithLocation_Click);
            m_CellToButtonWithLocation.Add(new Cell(i_Row, i_Column), buttonWithLocation);

            this.Controls.Add(buttonWithLocation);
        }

        private void buttonWithLocation_Click(object sender, EventArgs e)
        {
            ButtonWithLocation buttonWithLocation = sender as ButtonWithLocation;
            if (m_FirstCellTemporarilyOpenButton != buttonWithLocation)
            {
                m_Game.OpenCell(new Cell(buttonWithLocation.Row, buttonWithLocation.Column));
            }
        }

        private void m_Game_CellOpened(CellOpenedEventArgs i_CellOpenedEventArgs)
        {
            m_CellToButtonWithLocation[i_CellOpenedEventArgs.Cell].Text = i_CellOpenedEventArgs.Value.ToString();
            m_CellToButtonWithLocation[i_CellOpenedEventArgs.Cell].BackColor =
                m_Game.CurrentlyPlayingPlayer.Equals(m_Game.FirstPlayerWithScore.Player) ? m_FirstPlayerColor : m_SecondPlayerColor;
            if (m_FirstCellTemporarilyOpenButton == null)
            {
                m_FirstCellTemporarilyOpenButton = m_CellToButtonWithLocation[i_CellOpenedEventArgs.Cell];
                m_FirstCellTemporarilyOpenButton.Enabled = false;
            }
            else
            {
                m_SecondCellTemporarilyOpenButton = m_CellToButtonWithLocation[i_CellOpenedEventArgs.Cell];
                m_SecondCellTemporarilyOpenButton.Enabled = false;
            }
        }

        private void m_Game_TurnSwitched(CloseCellsEventArgs i_CloseCellsEventArgs)
        {
            MessageBox.Show("You were wrong. The cards will turn back now.", "Memory Game");

            m_CellToButtonWithLocation[i_CloseCellsEventArgs.FirstCell].BackColor = Color.FromName("Control");
            m_CellToButtonWithLocation[i_CloseCellsEventArgs.SecondCell].BackColor = Color.FromName("Control");
            m_CellToButtonWithLocation[i_CloseCellsEventArgs.FirstCell].Text = string.Empty;
            m_CellToButtonWithLocation[i_CloseCellsEventArgs.SecondCell].Text = string.Empty;

            m_FirstCellTemporarilyOpenButton.Enabled = true;
            m_SecondCellTemporarilyOpenButton.Enabled = true;

            m_FirstCellTemporarilyOpenButton = null;
            m_SecondCellTemporarilyOpenButton = null;

            setCurrentPlayerLabelText();
        }

        private void m_Game_ScoreChanged(ScoreChangesEventArgs i_ScoreChangesEventArgs)
        {
            m_FirstCellTemporarilyOpenButton = null;
            m_SecondCellTemporarilyOpenButton = null;

            setFirstPlayerLabel();
            setSecondPlayerLabel();
        }

        private void m_Game_GameEnded(GameEndedEventArgs i_GameEndedEventArgs)
        {
            string message = string.Format("Game Ended. The Winner is {0}!", i_GameEndedEventArgs.Winner.Name);
            MessageBox.Show(message, "Memory Game");
        }
    }
}